1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.tools.jconsole.inspector;
27
28
29 import java.awt.BorderLayout;
30 import java.awt.Color;
31 import java.awt.Component;
32 import java.awt.Dimension;
33 import java.awt.event.ActionEvent;
34 import java.awt.event.ActionListener;
35 import java.io.IOException;
36
37 import javax.management.IntrospectionException;
38 import javax.management.NotificationListener;
39 import javax.management.MBeanInfo;
40 import javax.management.InstanceNotFoundException;
41 import javax.management.ReflectionException;
42 import javax.management.MBeanAttributeInfo;
43 import javax.management.MBeanOperationInfo;
44 import javax.management.MBeanNotificationInfo;
45 import javax.management.Notification;
46 import javax.swing.BorderFactory;
47 import javax.swing.JButton;
48 import javax.swing.JOptionPane;
49 import javax.swing.JPanel;
50 import javax.swing.JScrollPane;
51 import javax.swing.JTextArea;
52 import javax.swing.SwingWorker;
53 import javax.swing.border.LineBorder;
54 import javax.swing.tree.DefaultMutableTreeNode;
55 import javax.swing.tree.DefaultTreeModel;
56
57 import sun.tools.jconsole.*;
58 import sun.tools.jconsole.inspector.XNodeInfo.Type;
59
60 import static sun.tools.jconsole.Resources.*;
61
62 @SuppressWarnings("serial")
63 public class XSheet extends JPanel
64 implements ActionListener, NotificationListener {
65
66 private JPanel mainPanel;
67 private JPanel southPanel;
68
69 private volatile DefaultMutableTreeNode currentNode;
70
71 private volatile XMBean mbean;
72
73 private XMBeanAttributes mbeanAttributes;
74
75 private XMBeanOperations mbeanOperations;
76
77 private XMBeanNotifications mbeanNotifications;
78
79 private XMBeanInfo mbeanInfo;
80
81 private JButton refreshButton;
82
83 private JButton clearButton, subscribeButton, unsubscribeButton;
84
85 private MBeansTab mbeansTab;
86
87 public XSheet(MBeansTab mbeansTab) {
88 this.mbeansTab = mbeansTab;
89 setupScreen();
90 }
91
92 public void dispose() {
93 clear();
94 XDataViewer.dispose(mbeansTab);
95 mbeanNotifications.dispose();
96 }
97
98 private void setupScreen() {
99 setLayout(new BorderLayout());
100 setBorder(BorderFactory.createLineBorder(Color.GRAY));
101
102 mainPanel = new JPanel();
103 mainPanel.setLayout(new BorderLayout());
104 add(mainPanel, BorderLayout.CENTER);
105
106 southPanel = new JPanel();
107 add(southPanel, BorderLayout.SOUTH);
108
109 String refreshButtonKey = "MBeansTab.refreshAttributesButton";
110 refreshButton = new JButton(getText(refreshButtonKey));
111 refreshButton.setMnemonic(getMnemonicInt(refreshButtonKey));
112 refreshButton.setToolTipText(getText(refreshButtonKey + ".toolTip"));
113 refreshButton.addActionListener(this);
114
115 String clearButtonKey = "MBeansTab.clearNotificationsButton";
116 clearButton = new JButton(getText(clearButtonKey));
117 clearButton.setMnemonic(getMnemonicInt(clearButtonKey));
118 clearButton.setToolTipText(getText(clearButtonKey + ".toolTip"));
119 clearButton.addActionListener(this);
120
121 String subscribeButtonKey = "MBeansTab.subscribeNotificationsButton";
122 subscribeButton = new JButton(getText(subscribeButtonKey));
123 subscribeButton.setMnemonic(getMnemonicInt(subscribeButtonKey));
124 subscribeButton.setToolTipText(getText(subscribeButtonKey + ".toolTip"));
125 subscribeButton.addActionListener(this);
126
127 String unsubscribeButtonKey = "MBeansTab.unsubscribeNotificationsButton";
128 unsubscribeButton = new JButton(getText(unsubscribeButtonKey));
129 unsubscribeButton.setMnemonic(getMnemonicInt(unsubscribeButtonKey));
130 unsubscribeButton.setToolTipText(getText(unsubscribeButtonKey + ".toolTip"));
131 unsubscribeButton.addActionListener(this);
132
133 mbeanAttributes = new XMBeanAttributes(mbeansTab);
134
135 mbeanOperations = new XMBeanOperations(mbeansTab);
136 mbeanOperations.addOperationsListener(this);
137
138 mbeanNotifications = new XMBeanNotifications();
139 mbeanNotifications.addNotificationsListener(this);
140
141 mbeanInfo = new XMBeanInfo();
142 }
143
144 private boolean isSelectedNode(DefaultMutableTreeNode n, DefaultMutableTreeNode cn) {
145 return (cn == n);
146 }
147
148
149 private void showErrorDialog(Object message, String title) {
150 new ThreadDialog(this, message, title, JOptionPane.ERROR_MESSAGE).run();
151 }
152
153 public boolean isMBeanNode(DefaultMutableTreeNode node) {
154 Object userObject = node.getUserObject();
155 if (userObject instanceof XNodeInfo) {
156 XNodeInfo uo = (XNodeInfo) userObject;
157 return uo.getType().equals(Type.MBEAN);
158 }
159 return false;
160 }
161
162
163 public synchronized void displayNode(DefaultMutableTreeNode node) {
164 clear();
165 displayEmptyNode();
166 if (node == null) {
167 return;
168 }
169 currentNode = node;
170 Object userObject = node.getUserObject();
171 if (userObject instanceof XNodeInfo) {
172 XNodeInfo uo = (XNodeInfo) userObject;
173 switch (uo.getType()) {
174 case MBEAN:
175 displayMBeanNode(node);
176 break;
177 case NONMBEAN:
178 displayEmptyNode();
179 break;
180 case ATTRIBUTES:
181 displayMBeanAttributesNode(node);
182 break;
183 case OPERATIONS:
184 displayMBeanOperationsNode(node);
185 break;
186 case NOTIFICATIONS:
187 displayMBeanNotificationsNode(node);
188 break;
189 case ATTRIBUTE:
190 case OPERATION:
191 case NOTIFICATION:
192 displayMetadataNode(node);
193 break;
194 default:
195 displayEmptyNode();
196 break;
197 }
198 } else {
199 displayEmptyNode();
200 }
201 }
202
203
204 private void displayMBeanNode(final DefaultMutableTreeNode node) {
205 final XNodeInfo uo = (XNodeInfo) node.getUserObject();
206 if (!uo.getType().equals(Type.MBEAN)) {
207 return;
208 }
209 mbean = (XMBean) uo.getData();
210 SwingWorker<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
211 @Override
212 public MBeanInfo doInBackground() throws InstanceNotFoundException,
213 IntrospectionException, ReflectionException, IOException {
214 return mbean.getMBeanInfo();
215 }
216 @Override
217 protected void done() {
218 try {
219 MBeanInfo mbi = get();
220 if (mbi != null) {
221 if (!isSelectedNode(node, currentNode)) {
222 return;
223 }
224 mbeanInfo.addMBeanInfo(mbean, mbi);
225 invalidate();
226 mainPanel.removeAll();
227 mainPanel.add(mbeanInfo, BorderLayout.CENTER);
228 southPanel.setVisible(false);
229 southPanel.removeAll();
230 validate();
231 repaint();
232 }
233 } catch (Exception e) {
234 Throwable t = Utils.getActualException(e);
235 if (JConsole.isDebug()) {
236 System.err.println("Couldn't get MBeanInfo for MBean [" +
237 mbean.getObjectName() + "]");
238 t.printStackTrace();
239 }
240 showErrorDialog(t.toString(),
241 Resources.getText("Problem displaying MBean"));
242 }
243 }
244 };
245 sw.execute();
246 }
247
248
249 private void displayMetadataNode(final DefaultMutableTreeNode node) {
250 final XNodeInfo uo = (XNodeInfo) node.getUserObject();
251 final XMBeanInfo mbi = mbeanInfo;
252 switch (uo.getType()) {
253 case ATTRIBUTE:
254 SwingWorker<MBeanAttributeInfo, Void> sw =
255 new SwingWorker<MBeanAttributeInfo, Void>() {
256 @Override
257 public MBeanAttributeInfo doInBackground() {
258 Object attrData = uo.getData();
259 mbean = (XMBean) ((Object[]) attrData)[0];
260 MBeanAttributeInfo mbai =
261 (MBeanAttributeInfo) ((Object[]) attrData)[1];
262 mbeanAttributes.loadAttributes(mbean, new MBeanInfo(
263 null, null, new MBeanAttributeInfo[]{mbai},
264 null, null, null));
265 return mbai;
266 }
267 @Override
268 protected void done() {
269 try {
270 MBeanAttributeInfo mbai = get();
271 if (!isSelectedNode(node, currentNode)) {
272 return;
273 }
274 invalidate();
275 mainPanel.removeAll();
276 JPanel attributePanel =
277 new JPanel(new BorderLayout());
278 JPanel attributeBorderPanel =
279 new JPanel(new BorderLayout());
280 attributeBorderPanel.setBorder(
281 BorderFactory.createTitledBorder(
282 Resources.getText("Attribute value")));
283 JPanel attributeValuePanel =
284 new JPanel(new BorderLayout());
285 attributeValuePanel.setBorder(
286 LineBorder.createGrayLineBorder());
287 attributeValuePanel.add(mbeanAttributes.getTableHeader(),
288 BorderLayout.PAGE_START);
289 attributeValuePanel.add(mbeanAttributes,
290 BorderLayout.CENTER);
291 attributeBorderPanel.add(attributeValuePanel,
292 BorderLayout.CENTER);
293 JPanel refreshButtonPanel = new JPanel();
294 refreshButtonPanel.add(refreshButton);
295 attributeBorderPanel.add(refreshButtonPanel,
296 BorderLayout.SOUTH);
297 refreshButton.setEnabled(true);
298 attributePanel.add(attributeBorderPanel,
299 BorderLayout.NORTH);
300 mbi.addMBeanAttributeInfo(mbai);
301 attributePanel.add(mbi, BorderLayout.CENTER);
302 mainPanel.add(attributePanel,
303 BorderLayout.CENTER);
304 southPanel.setVisible(false);
305 southPanel.removeAll();
306 validate();
307 repaint();
308 } catch (Exception e) {
309 Throwable t = Utils.getActualException(e);
310 if (JConsole.isDebug()) {
311 System.err.println("Problem displaying MBean " +
312 "attribute for MBean [" +
313 mbean.getObjectName() + "]");
314 t.printStackTrace();
315 }
316 showErrorDialog(t.toString(),
317 Resources.getText("Problem displaying MBean"));
318 }
319 }
320 };
321 sw.execute();
322 break;
323 case OPERATION:
324 Object operData = uo.getData();
325 mbean = (XMBean) ((Object[]) operData)[0];
326 MBeanOperationInfo mboi =
327 (MBeanOperationInfo) ((Object[]) operData)[1];
328 mbeanOperations.loadOperations(mbean,
329 new MBeanInfo(null, null, null, null,
330 new MBeanOperationInfo[]{mboi}, null));
331 invalidate();
332 mainPanel.removeAll();
333 JPanel operationPanel = new JPanel(new BorderLayout());
334 JPanel operationBorderPanel = new JPanel(new BorderLayout());
335 operationBorderPanel.setBorder(BorderFactory.createTitledBorder(
336 Resources.getText("Operation invocation")));
337 operationBorderPanel.add(new JScrollPane(mbeanOperations));
338 operationPanel.add(operationBorderPanel, BorderLayout.NORTH);
339 mbi.addMBeanOperationInfo(mboi);
340 operationPanel.add(mbi, BorderLayout.CENTER);
341 mainPanel.add(operationPanel, BorderLayout.CENTER);
342 southPanel.setVisible(false);
343 southPanel.removeAll();
344 validate();
345 repaint();
346 break;
347 case NOTIFICATION:
348 Object notifData = uo.getData();
349 invalidate();
350 mainPanel.removeAll();
351 mbi.addMBeanNotificationInfo((MBeanNotificationInfo) notifData);
352 mainPanel.add(mbi, BorderLayout.CENTER);
353 southPanel.setVisible(false);
354 southPanel.removeAll();
355 validate();
356 repaint();
357 break;
358 }
359 }
360
361
362 private void displayMBeanAttributesNode(final DefaultMutableTreeNode node) {
363 final XNodeInfo uo = (XNodeInfo) node.getUserObject();
364 if (!uo.getType().equals(Type.ATTRIBUTES)) {
365 return;
366 }
367 mbean = (XMBean) uo.getData();
368 final XMBean xmb = mbean;
369 SwingWorker<MBeanInfo,Void> sw = new SwingWorker<MBeanInfo,Void>() {
370 @Override
371 public MBeanInfo doInBackground() throws InstanceNotFoundException,
372 IntrospectionException, ReflectionException, IOException {
373 MBeanInfo mbi = xmb.getMBeanInfo();
374 return mbi;
375 }
376 @Override
377 protected void done() {
378 try {
379 MBeanInfo mbi = get();
380 if (mbi != null && mbi.getAttributes() != null &&
381 mbi.getAttributes().length > 0) {
382
383 mbeanAttributes.loadAttributes(xmb, mbi);
384
385 if (!isSelectedNode(node, currentNode)) {
386 return;
387 }
388 invalidate();
389 mainPanel.removeAll();
390 JPanel borderPanel = new JPanel(new BorderLayout());
391 borderPanel.setBorder(BorderFactory.createTitledBorder(
392 Resources.getText("Attribute values")));
393 borderPanel.add(new JScrollPane(mbeanAttributes));
394 mainPanel.add(borderPanel, BorderLayout.CENTER);
395
396 southPanel.removeAll();
397 southPanel.add(refreshButton, BorderLayout.SOUTH);
398 southPanel.setVisible(true);
399 refreshButton.setEnabled(true);
400 validate();
401 repaint();
402 }
403 } catch (Exception e) {
404 Throwable t = Utils.getActualException(e);
405 if (JConsole.isDebug()) {
406 System.err.println("Problem displaying MBean " +
407 "attributes for MBean [" +
408 mbean.getObjectName() + "]");
409 t.printStackTrace();
410 }
411 showErrorDialog(t.toString(),
412 Resources.getText("Problem displaying MBean"));
413 }
414 }
415 };
416 sw.execute();
417 }
418
419
420 private void displayMBeanOperationsNode(final DefaultMutableTreeNode node) {
421 final XNodeInfo uo = (XNodeInfo) node.getUserObject();
422 if (!uo.getType().equals(Type.OPERATIONS)) {
423 return;
424 }
425 mbean = (XMBean) uo.getData();
426 SwingWorker<MBeanInfo, Void> sw = new SwingWorker<MBeanInfo, Void>() {
427 @Override
428 public MBeanInfo doInBackground() throws InstanceNotFoundException,
429 IntrospectionException, ReflectionException, IOException {
430 return mbean.getMBeanInfo();
431 }
432 @Override
433 protected void done() {
434 try {
435 MBeanInfo mbi = get();
436 if (mbi != null) {
437 if (!isSelectedNode(node, currentNode)) {
438 return;
439 }
440 mbeanOperations.loadOperations(mbean, mbi);
441 invalidate();
442 mainPanel.removeAll();
443 JPanel borderPanel = new JPanel(new BorderLayout());
444 borderPanel.setBorder(BorderFactory.createTitledBorder(
445 Resources.getText("Operation invocation")));
446 borderPanel.add(new JScrollPane(mbeanOperations));
447 mainPanel.add(borderPanel, BorderLayout.CENTER);
448 southPanel.setVisible(false);
449 southPanel.removeAll();
450 validate();
451 repaint();
452 }
453 } catch (Exception e) {
454 Throwable t = Utils.getActualException(e);
455 if (JConsole.isDebug()) {
456 System.err.println("Problem displaying MBean " +
457 "operations for MBean [" +
458 mbean.getObjectName() + "]");
459 t.printStackTrace();
460 }
461 showErrorDialog(t.toString(),
462 Resources.getText("Problem displaying MBean"));
463 }
464 }
465 };
466 sw.execute();
467 }
468
469
470 private void displayMBeanNotificationsNode(DefaultMutableTreeNode node) {
471 final XNodeInfo uo = (XNodeInfo) node.getUserObject();
472 if (!uo.getType().equals(Type.NOTIFICATIONS)) {
473 return;
474 }
475 mbean = (XMBean) uo.getData();
476 mbeanNotifications.loadNotifications(mbean);
477 updateNotifications();
478 invalidate();
479 mainPanel.removeAll();
480 JPanel borderPanel = new JPanel(new BorderLayout());
481 borderPanel.setBorder(BorderFactory.createTitledBorder(
482 Resources.getText("Notification buffer")));
483 borderPanel.add(new JScrollPane(mbeanNotifications));
484 mainPanel.add(borderPanel, BorderLayout.CENTER);
485
486 southPanel.removeAll();
487 southPanel.add(subscribeButton, BorderLayout.WEST);
488 southPanel.add(unsubscribeButton, BorderLayout.CENTER);
489 southPanel.add(clearButton, BorderLayout.EAST);
490 southPanel.setVisible(true);
491 subscribeButton.setEnabled(true);
492 unsubscribeButton.setEnabled(true);
493 clearButton.setEnabled(true);
494 validate();
495 repaint();
496 }
497
498
499 private void displayEmptyNode() {
500 invalidate();
501 mainPanel.removeAll();
502 southPanel.removeAll();
503 validate();
504 repaint();
505 }
506
507
508
509
510 private void registerListener() {
511 new SwingWorker<Void, Void>() {
512 @Override
513 public Void doInBackground()
514 throws InstanceNotFoundException, IOException {
515 mbeanNotifications.registerListener(currentNode);
516 return null;
517 }
518 @Override
519 protected void done() {
520 try {
521 get();
522 updateNotifications();
523 validate();
524 } catch (Exception e) {
525 Throwable t = Utils.getActualException(e);
526 if (JConsole.isDebug()) {
527 System.err.println("Problem adding listener");
528 t.printStackTrace();
529 }
530 showErrorDialog(t.getMessage(),
531 Resources.getText("Problem adding listener"));
532 }
533 }
534 }.execute();
535 }
536
537
538
539
540 private void unregisterListener() {
541 new SwingWorker<Boolean, Void>() {
542 @Override
543 public Boolean doInBackground() {
544 return mbeanNotifications.unregisterListener(currentNode);
545 }
546 @Override
547 protected void done() {
548 try {
549 if (get()) {
550 updateNotifications();
551 validate();
552 }
553 } catch (Exception e) {
554 Throwable t = Utils.getActualException(e);
555 if (JConsole.isDebug()) {
556 System.err.println("Problem removing listener");
557 t.printStackTrace();
558 }
559 showErrorDialog(t.getMessage(),
560 Resources.getText("Problem removing listener"));
561 }
562 }
563 }.execute();
564 }
565
566
567
568
569 private void refreshAttributes() {
570 mbeanAttributes.refreshAttributes();
571 }
572
573
574 private void updateNotifications() {
575 if (mbeanNotifications.isListenerRegistered(mbean)) {
576 long received = mbeanNotifications.getReceivedNotifications(mbean);
577 updateReceivedNotifications(currentNode, received, false);
578 } else {
579 clearNotifications();
580 }
581 }
582
583
584
585
586
587 private void updateReceivedNotifications(
588 DefaultMutableTreeNode emitter, long received, boolean bold) {
589 String text = Resources.getText("Notifications") + "[" + received + "]";
590 DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) mbeansTab.getTree().getLastSelectedPathComponent();
591 if (bold && emitter != selectedNode) {
592 text = "<html><b>" + text + "</b></html>";
593 }
594 updateNotificationsNodeLabel(emitter, text);
595 }
596
597
598
599
600
601 private void clearNotifications() {
602 updateNotificationsNodeLabel(currentNode,
603 Resources.getText("Notifications"));
604 }
605
606
607
608
609
610 private void clearNotifications0() {
611 updateNotificationsNodeLabel(currentNode,
612 Resources.getText("Notifications") + "[0]");
613 }
614
615
616
617
618
619 private void updateNotificationsNodeLabel(
620 DefaultMutableTreeNode node, String label) {
621 synchronized (mbeansTab.getTree()) {
622 invalidate();
623 XNodeInfo oldUserObject = (XNodeInfo) node.getUserObject();
624 XNodeInfo newUserObject = new XNodeInfo(
625 oldUserObject.getType(), oldUserObject.getData(),
626 label, oldUserObject.getToolTipText());
627 node.setUserObject(newUserObject);
628 DefaultTreeModel model =
629 (DefaultTreeModel) mbeansTab.getTree().getModel();
630 model.nodeChanged(node);
631 validate();
632 repaint();
633 }
634 }
635
636
637
638
639
640 private void clearCurrentNotifications() {
641 mbeanNotifications.clearCurrentNotifications();
642 if (mbeanNotifications.isListenerRegistered(mbean)) {
643
644
645
646
647
648 clearNotifications0();
649 } else {
650
651
652
653
654
655 clearNotifications();
656 }
657 }
658
659
660 private void clear() {
661 mbeanAttributes.stopCellEditing();
662 mbeanAttributes.emptyTable();
663 mbeanAttributes.removeAttributes();
664 mbeanOperations.removeOperations();
665 mbeanNotifications.stopCellEditing();
666 mbeanNotifications.emptyTable();
667 mbeanNotifications.disableNotifications();
668 mbean = null;
669 currentNode = null;
670 }
671
672
673
674
675
676
677 public void handleNotification(Notification e, Object handback) {
678
679 if (e.getType().equals(XOperations.OPERATION_INVOCATION_EVENT)) {
680 final Object message;
681 if (handback == null) {
682 JTextArea textArea = new JTextArea("null");
683 textArea.setEditable(false);
684 textArea.setEnabled(true);
685 textArea.setRows(textArea.getLineCount());
686 message = textArea;
687 } else {
688 Component comp = mbeansTab.getDataViewer().
689 createOperationViewer(handback, mbean);
690 if (comp == null) {
691 JTextArea textArea = new JTextArea(handback.toString());
692 textArea.setEditable(false);
693 textArea.setEnabled(true);
694 textArea.setRows(textArea.getLineCount());
695 JScrollPane scrollPane = new JScrollPane(textArea);
696 Dimension d = scrollPane.getPreferredSize();
697 if (d.getWidth() > 400 || d.getHeight() > 250) {
698 scrollPane.setPreferredSize(new Dimension(400, 250));
699 }
700 message = scrollPane;
701 } else {
702 if (!(comp instanceof JScrollPane)) {
703 comp = new JScrollPane(comp);
704 }
705 Dimension d = comp.getPreferredSize();
706 if (d.getWidth() > 400 || d.getHeight() > 250) {
707 comp.setPreferredSize(new Dimension(400, 250));
708 }
709 message = comp;
710 }
711 }
712 new ThreadDialog(
713 (Component) e.getSource(),
714 message,
715 Resources.getText("Operation return value"),
716 JOptionPane.INFORMATION_MESSAGE).run();
717 }
718 else if (e.getType().equals(
719 XMBeanNotifications.NOTIFICATION_RECEIVED_EVENT)) {
720 DefaultMutableTreeNode emitter = (DefaultMutableTreeNode) handback;
721 Long received = (Long) e.getUserData();
722 updateReceivedNotifications(emitter, received.longValue(), true);
723 }
724 }
725
726
727
728
729
730 public void actionPerformed(ActionEvent e) {
731 if (e.getSource() instanceof JButton) {
732 JButton button = (JButton) e.getSource();
733
734 if (button == refreshButton) {
735 refreshAttributes();
736 return;
737 }
738
739 if (button == clearButton) {
740 clearCurrentNotifications();
741 return;
742 }
743
744 if (button == subscribeButton) {
745 registerListener();
746 return;
747 }
748
749 if (button == unsubscribeButton) {
750 unregisterListener();
751 return;
752 }
753 }
754 }
755 }